package org.raymond.iworks.study.basic.structure.linkedlist;

/**
 * @author raymond
 * @version V1.0
 * @Description: TODO
 */
public class SingleLinkedList {
    private HeroNode head = new HeroNode(0, "", "");

    /**
     * 分析:当不考虑编号顺序时
     * 1, 找到当前链表的最后节点
     * 2, 将最后这个节点的next指向新的节点
     */
    public void add(HeroNode node){
        /**
         * 因为head节点不能动,因此我们需要一个辅助遍历temp
         */
        HeroNode tmp = head;
        // 遍历链表,找到最后一个Node
        while(true){
            // 找到链表的最后一个node
            if(tmp.next==null){
                break;
            }
            // 如果没有找到最后,就将temp后移
            tmp = tmp.next;
        }
        // 退出while时,tmp就指向了链表的最后一个node
        tmp=node;
    }

    /**
     * 按英雄排名顺序添加
     * 如果有这个排名,则添加失败,并给出提示
     * 1, 通过遍历,在linkedlist中找到新添加的节点的插入位置
     * 2, temp=插入位置前一个节点
     * 3, newAdded.next=temp.next
     * 4, temp.next = newAdded
     */
    public void addByOrder(HeroNode node){
        // 因为头节点不能动,仍然需要通过一个tmp变量来帮助找到插入的位置
        // 因为是单链表,因此tmp应该是位于插入位置的前一个节点,否则无法添加
        HeroNode tmp = head;
        boolean flag = false; // flag标志添加的编号是否存在,默认为false;
        while(true){
            // 判断是否已经遍历到链表的最后一个节点
            if(tmp.next == null){
                break;
            }
            // tmp节点的排序编号大于将要插入的节点编号,即tmp在新插入的节点之前,此时就可以将新接入接入tmp后面
            if(tmp.next.no>node.no){
                break;
            }else if(tmp.next.no==node.no){
                // 编号已存在
                flag = true;
                break;
            }
            // 未break,后移
            tmp = tmp.next;
        }
        if(flag){
            System.err.println(String.format("编号%d重复,不能添加", node.no));
        }else{
            node=tmp.next;
            tmp=node;
        }
    }

    // 修改节点信息,根据no编号来修改,且不改no
    public void update(HeroNode update){
        if(isEmpty()){
            System.err.println("链表为空");
            return;
        }
        // 找到需要修改的节点
        HeroNode tmp = head;
        // 是否找到该节点
        boolean flag = false;
        while(true){
            if(tmp==null) break;
            if(tmp.no== update.no){
                flag = true;
                break;
            }
            tmp = tmp.next;
        }
        if(flag){
            tmp.name=update.name;
            tmp.nickName=update.nickName;
        }else{
            System.out.println("没有找到待修改的节点");
        }
    }

    public void delete(HeroNode del){
        if(isEmpty()){
            System.err.println("链表为空");
            return;
        }
        // 找到需要删除的节点
        HeroNode tmp = head;
        // 是否找到该节点
        boolean flag = false;
        while(true){
            if(tmp==null || tmp.next==null) break;
            // tmp是待删除节点的前一个节点,即判断节点是否要删除时,总是找下一个节点的数据来判断.
            // 因为单向链表最多只能操作两个节点:当前节点和下一个节点.
            // 要删除链表中的一个节点,即断开该节点与其他节点的连接.
            // 在单向链表中,只能断开当前节点与下一节点的连接,因此就只能根据下一个节点的数据来判断
            if(tmp.next.no== del.no){
                flag = true;
                break;
            }
            tmp = tmp.next;
        }
        if(flag){
            tmp=tmp.next.next;
        }else{
            System.out.println("没有找到待删除的节点");
        }
    }

    public boolean isEmpty(){
        return head.next==null;
    }

    public HeroNode head(){
        return head;
    }

    public void list(){
        // 判断链表是否为空
        if(isEmpty()){
            System.err.println("链表为空");
            return;
        }
        // 因为头节点不能动,因此需要一个辅助变量来遍历
        HeroNode tmp = head.next;
        while(true){
            if(tmp==null) break;
            System.out.println(tmp);
            // 将tmp后移
            tmp = tmp.next;
        }
    }
}
